package dao

import (
	"context"
	"fmt"
	"strconv"
	"time"

	"github.com/go-redis/redis/v8"
	"gorm.io/gorm"

	"server/app/model"
	"server/pkg/utils"
)

type User struct {
	db    *gorm.DB
	redis *redis.Client
}

func NewUser() *User {
	return &User{
		db:    utils.DB,
		redis: utils.RedisConn,
	}
}

func (u *User) Transaction(f func(tx *gorm.DB) error) error {
	return u.db.Transaction(f)
}

func (u *User) FirstByUsername(username string) (*model.User, error) {
	user := &model.User{}
	err := u.db.Debug().Where("username = ?", username).First(user).Error
	if err != nil {
		return nil, err
	}
	return user, nil
}

func (u *User) TxFirstByUsername(tx *gorm.DB, username string) (*model.User, error) {
	user := &model.User{}
	err := tx.Debug().Where("username = ?", username).First(user).Error
	if err != nil {
		return nil, err
	}
	return user, nil
}

const (
	_uaCountKey = "username:ua:%s:%s"
)

func (u *User) CountByUA(username, ua string) (int, error) {
	result, err := u.redis.Get(context.Background(), fmt.Sprintf(_uaCountKey, username, ua)).Result()
	if err != nil && err != redis.Nil {
		return 0, err
	}
	if err == redis.Nil {
		return 0, nil
	}
	res, err := strconv.Atoi(result)
	if err != nil {
		return 0, err
	}
	return res, nil
}

func (u *User) UpdateCountByUA(username, ua string, cnt int, expire time.Duration) error {
	return u.redis.Set(context.Background(), fmt.Sprintf(_uaCountKey, username, ua), cnt, expire).Err()
}

func (u *User) ResetCountByUA(username, ua string) error {
	return u.redis.Del(context.Background(), fmt.Sprintf(_uaCountKey, username, ua)).Err()
}

func (u *User) InsertUser(user *model.User) error {
	return u.db.Debug().Create(user).Error
}

func (u *User) TxInsertUser(tx *gorm.DB, user *model.User) error {
	return tx.Debug().Create(user).Error
}
